package value

import (
	"context"
	"fmt"
	"github.com/samber/lo"
	"sort"
	"tongquetai_server/activity_vk/domain/manage/common/static_data"
)

// TaskShowTyp 成就展示类型
type TaskShowTyp int

func (t TaskShowTyp) Val() int {
	return int(t)
}

// docs: https://xmdc.yuque.com/hgngvk/dvagbh/fryh5a8ahcniuihc#hEQku
const (
	DefaultTaskShowTyp   TaskShowTyp = 0 // 处理不传给服务端的场景
	OrdinaryTaskShowTyp  TaskShowTyp = 1 // 普通挑战成就
	SeasonTaskShowTyp    TaskShowTyp = 2 // 赛季挑战成就
	ValentineTaskShowTyp TaskShowTyp = 3 // 情人节成就
	PalaceTaskShowTyp    TaskShowTyp = 4
)

// TaskNoStart 挑战成就编号起始值
type TaskNoStart int

func (t TaskNoStart) Val() int {
	return int(t)
}

const (
	SeasonTaskNoStart = 10001 // 赛季挑战成就，从10001开始
)

// @META.table:json
/*
[
    ["挑战成就配置"],
    ["序号", "任务类型", "任务要求", "奖励内容", "奖励内容"],
    [1, "同时上阵{0}个英雄", 100, "金币*10", "金币*10"],
    [2, "同时上阵{0}个英雄", 120, "金币*10", "金币*10"],
    [3, "同时上阵{0}个英雄", 121, "金币*10", "金币*10"]
]
*/

// TqtActivityTask 成就任务
// @META.struct:tqt
type TqtActivityTask struct {
	No         int        `json:"no" header:"序号" validate:"gt=0"`
	TypName    string     `json:"typName" header:"任务类型" validate:"required"`
	Typ        int        `json:"typ" skipField:"true" validate:"gt=0"`
	RequireVal int        `json:"requireVal" header:"任务要求"  validate:"gte=0"`
	Award      []TqtAward `json:"award" header:"奖励内容" validate:"gt=0,dive"`
}

// TqtDailyResetTask 任务类型配置
// @META.struct:tqt
type TqtDailyResetTask struct {
	TypName      string `json:"typName" header:"任务类型" validate:"required"`
	Typ          int    `json:"typ" skipField:"true" validate:"gt=0"`
	IsDailyReset bool   `json:"isDailyReset" header:"是否每日重置" true:"是" false:"否"`
}

func (t *TqtActivityTask) Call(ctx context.Context) (err error) {
	actType := ctx.Value("actType").(int)
	taskMap, err := static_data.GetTaskTypeInfo().GetNameIdMap(ctx, actType)
	if err != nil {
		return
	}
	taskId, ok := taskMap[t.TypName]
	if !ok {
		return fmt.Errorf("任务类型[%s]不存在", t.TypName)
	}
	t.Typ = taskId
	return
}

func (t *TqtDailyResetTask) Call(ctx context.Context) (err error) {
	actType := ctx.Value("actType").(int)
	taskMap, err := static_data.GetTaskTypeInfo().GetNameIdMap(ctx, actType)
	if err != nil {
		return
	}
	taskId, ok := taskMap[t.TypName]
	if !ok {
		return fmt.Errorf("任务类型[%s]不存在", t.TypName)
	}
	t.Typ = taskId
	return
}

// 服务端
// @META.struct:svr
type SvrActivityTask struct {
	ShowOutsideId           string                `json:"show_outside_id"`
	SeasonTaskShowOutsideId string                `json:"season_task_show_outside_id"` // 赛季成就外置显示游戏对象id
	Item                    []SvrActivityTaskItem `json:"item"`
	DailyResetTask          []int                 `json:"daily_reset_task"` // 任务类型配置 => 仅存放需要重置的任务类型
}
// @META.struct:svr
type SvrActivityTaskItem struct {
	No         int        `json:"no"`
	Typ        int        `json:"typ"`
	RequireVal int        `json:"require_val"`
	Award      []SvrAward `json:"award"`
	ShowTyp    int        `json:"show_typ"`
}

// ------------------------------------ 适配器 -----------------------------------

type TqtActivityTaskAgg struct {
	ShowTyp            TaskShowTyp         // 展示类型
	ShowOutside        TqtItem             // 外置显示道具
	ActivityTaskList   []TqtActivityTask   // 成就任务
	DailyResetTaskList []TqtDailyResetTask // 任务类型配置
}

/*
仅适用单个成就任务 (成就任务 + 任务类型配置 + 外置图标)
*/

func ToTqtActivityTask(ctx context.Context, actType int, svrActivityTask SvrActivityTask) (activityTaskAgg TqtActivityTaskAgg, err error) {
	// 静态表
	taskMap, err := static_data.GetTaskTypeInfo().GetIdNameMap(ctx, actType)
	if err != nil {
		return
	}
	if len(svrActivityTask.Item) == 0 {
		return
	}

	// 需要重置的任务
	svrTaskTypSet := make(map[int]struct{}, len(svrActivityTask.DailyResetTask))
	for _, taskTyp := range svrActivityTask.DailyResetTask {
		svrTaskTypSet[taskTyp] = struct{}{}
	}

	// 任务类型重置
	tqtDailyResetTaskList := make([]TqtDailyResetTask, 0, len(svrActivityTask.Item))
	tqtDailyResetTaskSet := make(map[int]struct{}, 4)
	var isDailyReset bool
	for _, v := range svrActivityTask.Item {
		// 过滤已经存在的
		if _, ok := tqtDailyResetTaskSet[v.Typ]; ok {
			continue
		}
		tqtDailyResetTaskSet[v.Typ] = struct{}{}

		isDailyReset = false
		if _, ok := svrTaskTypSet[v.Typ]; ok {
			isDailyReset = true
		}
		tqtDailyResetTaskList = append(tqtDailyResetTaskList, TqtDailyResetTask{
			Typ:          v.Typ,
			TypName:      taskMap[v.Typ],
			IsDailyReset: isDailyReset,
		})
	}

	// 任务奖励配置
	tqtActivityTaskList := make([]TqtActivityTask, 0, len(svrActivityTask.Item))
	for _, v := range svrActivityTask.Item {
		tqtActivityTaskList = append(tqtActivityTaskList, TqtActivityTask{
			No:         v.No,
			Typ:        v.Typ,
			TypName:    taskMap[v.Typ],
			RequireVal: v.RequireVal,
			Award:      SvrToTqtAwards(ctx, v.Award),
		})
	}

	var showOutside TqtItem
	var showTyp = svrActivityTask.Item[0].ShowTyp
	switch showTyp {
	case SeasonTaskShowTyp.Val():
		// 赛季成就奖励
		showOutside = toTqtSeasonOutside(ctx, SvrItem{GameObjectId: svrActivityTask.SeasonTaskShowOutsideId})
	default:
		// 其他奖励
		showOutside = toTqtSeasonOutside(ctx, SvrItem{GameObjectId: svrActivityTask.ShowOutsideId})
	}

	activityTaskAgg = TqtActivityTaskAgg{
		ActivityTaskList:   tqtActivityTaskList,
		ShowOutside:        showOutside,
		ShowTyp:            TaskShowTyp(showTyp),
		DailyResetTaskList: tqtDailyResetTaskList,
	}

	return
}

func ToSvrActivityTask(activityTaskAgg TqtActivityTaskAgg) (svrActivityTask SvrActivityTask) {
	// 任务类型重置 => 仅存放需要重置的任务类型
	svrDailyResetTask := make([]int, 0, len(activityTaskAgg.DailyResetTaskList))
	for _, item := range activityTaskAgg.DailyResetTaskList {
		if item.IsDailyReset == true {
			svrDailyResetTask = append(svrDailyResetTask, item.Typ)
		}
	}

	// 任务奖励配置
	svrActivityTaskItem := make([]SvrActivityTaskItem, len(activityTaskAgg.ActivityTaskList))
	for i, v := range activityTaskAgg.ActivityTaskList {
		svrActivityTaskItem[i] = SvrActivityTaskItem{
			No:         v.No,
			Typ:        v.Typ,
			RequireVal: v.RequireVal,
			Award:      TqtToSvrAwards(v.Award),
			ShowTyp:    activityTaskAgg.ShowTyp.Val(),
		}
	}

	switch activityTaskAgg.ShowTyp {
	case SeasonTaskShowTyp:
		// 赛季成就奖励
		svrActivityTask = SvrActivityTask{
			ShowOutsideId:           "",
			SeasonTaskShowOutsideId: toSvrSeasonOutSide(activityTaskAgg.ShowOutside).GameObjectId,
			Item:                    svrActivityTaskItem,
			DailyResetTask:          svrDailyResetTask,
		}
	default:
		// 其他奖励
		svrActivityTask = SvrActivityTask{
			ShowOutsideId:           toSvrSeasonOutSide(activityTaskAgg.ShowOutside).GameObjectId,
			SeasonTaskShowOutsideId: "",
			Item:                    svrActivityTaskItem,
			DailyResetTask:          svrDailyResetTask,
		}
	}

	return
}

func toTqtSeasonOutside(ctx context.Context, item SvrItem) (tqtShowOutSide TqtItem) {
	// 道具不存在时
	if len(item.GameObjectId) == 0 {
		return
	}
	// 道具存在时
	tqtShowOutSide = SvrToTqtItem(ctx, item)
	return
}

func toSvrSeasonOutSide(tqtOutside TqtItem) (svrItem SvrItem) {
	svrItem = SvrItem{}
	if len(tqtOutside.ItemId) > 0 {
		svrItem = TqtToSvrItem(tqtOutside)
	}
	return
}

/**
仅适用"赛季+普通"组合
本业务逻辑不处理"任务类型配置"(DailyResetTask)
*/

// ToTqtActivityTaskAgg 赛季+普通 成就挑战
func ToTqtActivityTaskAgg(ctx context.Context, actType int, svrActivityTask SvrActivityTask) (activityTaskAggSet map[TaskShowTyp]TqtActivityTaskAgg, err error) {
	// 按照showTyp聚合
	svrActivityTaskGroupByShowTyp := lo.GroupBy(svrActivityTask.Item, func(item SvrActivityTaskItem) int {
		return item.ShowTyp
	})

	activityTaskAggSet = make(map[TaskShowTyp]TqtActivityTaskAgg, 2)
	// 转成相应的哈希
	for showTyp, item := range svrActivityTaskGroupByShowTyp {
		activityTaskAgg, err1 := ToTqtActivityTask(ctx, actType, SvrActivityTask{
			ShowOutsideId:           svrActivityTask.ShowOutsideId,
			SeasonTaskShowOutsideId: svrActivityTask.SeasonTaskShowOutsideId,
			Item:                    item,
		})
		if err1 != nil {
			return
		}
		activityTaskAggSet[TaskShowTyp(showTyp)] = activityTaskAgg
	}

	return
}

// ToSvrActivityTaskAgg 赛季+普通 成就挑战
func ToSvrActivityTaskAgg(activityTaskAggSet map[TaskShowTyp]TqtActivityTaskAgg) (svrActivityTask SvrActivityTask, err error) {
	var (
		showOutSide         string
		seasonShowOutside   string
		svrActivityTaskItem = make([]SvrActivityTaskItem, 0, 4)
	)
	for showTyp, taskAgg := range activityTaskAggSet {
		svrTask := ToSvrActivityTask(taskAgg)
		svrActivityTaskItem = append(svrActivityTaskItem, svrTask.Item...)
		if showTyp == SeasonTaskShowTyp {
			seasonShowOutside = svrTask.SeasonTaskShowOutsideId
		} else {
			showOutSide = svrTask.ShowOutsideId
		}
	}

	// 正序
	sort.Slice(svrActivityTaskItem, func(i, j int) bool {
		return svrActivityTaskItem[i].ShowTyp < svrActivityTaskItem[j].ShowTyp
	})

	svrActivityTask = SvrActivityTask{
		ShowOutsideId:           showOutSide,
		SeasonTaskShowOutsideId: seasonShowOutside,
		Item:                    svrActivityTaskItem,
	}
	return
}

/**
仅适用"地宫+普通"组合
*/

func ToPalaceSvrActivityTask(tqtActivityTask, palaceTask []TqtActivityTask, tqtDailyResetTask []TqtDailyResetTask) (svrTask SvrActivityTask) {
	svrActivityTaskItems := make([]SvrActivityTaskItem, 0, len(tqtActivityTask)+len(palaceTask))
	svrDailyResetTask := make([]int, 0, len(tqtDailyResetTask))
	for _, v := range tqtActivityTask {
		svrActivityTaskItems = append(svrActivityTaskItems, SvrActivityTaskItem{
			No:         v.No,
			Typ:        v.Typ,
			RequireVal: v.RequireVal,
			Award:      TqtToSvrAwards(v.Award),
			ShowTyp:    OrdinaryTaskShowTyp.Val(),
		})
	}

	for _, v := range palaceTask {
		svrActivityTaskItems = append(svrActivityTaskItems, SvrActivityTaskItem{
			No:         v.No,
			Typ:        v.Typ,
			RequireVal: v.RequireVal,
			Award:      TqtToSvrAwards(v.Award),
			ShowTyp:    PalaceTaskShowTyp.Val(),
		})
	}

	for _, v := range tqtDailyResetTask {
		if v.IsDailyReset {
			svrDailyResetTask = append(svrDailyResetTask, v.Typ)
		}
	}
	return SvrActivityTask{
		Item:           svrActivityTaskItems,
		DailyResetTask: svrDailyResetTask,
	}
}

func TpPalaceTqtActivityTask(ctx context.Context, actType int, svrActivityTask SvrActivityTask) (tqtActivityTask, palaceTask []TqtActivityTask, tqtDailyResetTask []TqtDailyResetTask, err error) {
	taskMap, err := static_data.GetTaskTypeInfo().GetIdNameMap(ctx, actType)
	if err != nil {
		return
	}
	tqtActivityTask = make([]TqtActivityTask, 0, len(svrActivityTask.Item))
	palaceTask = make([]TqtActivityTask, 0, len(svrActivityTask.Item))
	tqtDailyResetTask = make([]TqtDailyResetTask, 0, len(taskMap))
	set := make(map[int]struct{}, 0)
	for _, v := range svrActivityTask.Item {
		if v.ShowTyp == OrdinaryTaskShowTyp.Val() {
			tqtActivityTask = append(tqtActivityTask, TqtActivityTask{
				No:         v.No,
				TypName:    taskMap[v.Typ],
				Typ:        v.Typ,
				RequireVal: v.RequireVal,
				Award:      SvrToTqtAwards(ctx, v.Award),
			})
		} else {
			palaceTask = append(palaceTask, TqtActivityTask{
				No:         v.No,
				TypName:    taskMap[v.Typ],
				Typ:        v.Typ,
				RequireVal: v.RequireVal,
				Award:      SvrToTqtAwards(ctx, v.Award),
			})
		}

	}
	for _, v := range svrActivityTask.DailyResetTask {
		tqtDailyResetTask = append(tqtDailyResetTask, TqtDailyResetTask{
			TypName:      taskMap[v],
			Typ:          v,
			IsDailyReset: true,
		})
		set[v] = struct{}{}
	}

	for key, val := range taskMap {
		_, ok := set[key]
		if !ok {
			tqtDailyResetTask = append(tqtDailyResetTask, TqtDailyResetTask{
				TypName:      val,
				Typ:          key,
				IsDailyReset: false,
			})
		}
	}
	return
}

/*
仅适用单个成就任务 (成就任务 + 任务类型配置 )没有 外置图标
*/

func ToTqtActivityTaskOne(ctx context.Context, actType int, svrActivityTask SvrActivityTask) (activityTaskAgg TqtActivityTaskAgg, err error) {
	// 静态表
	taskMap, err := static_data.GetTaskTypeInfo().GetIdNameMap(ctx, actType)
	if err != nil {
		return
	}
	if len(svrActivityTask.Item) == 0 {
		return
	}

	// 需要重置的任务
	svrTaskTypSet := make(map[int]struct{}, len(svrActivityTask.DailyResetTask))
	for _, taskTyp := range svrActivityTask.DailyResetTask {
		svrTaskTypSet[taskTyp] = struct{}{}
	}

	// 任务类型重置
	tqtDailyResetTaskList := make([]TqtDailyResetTask, 0, len(svrActivityTask.Item))
	tqtDailyResetTaskSet := make(map[int]struct{}, 4)
	var isDailyReset bool
	for _, v := range svrActivityTask.Item {
		// 过滤已经存在的
		if _, ok := tqtDailyResetTaskSet[v.Typ]; ok {
			continue
		}
		tqtDailyResetTaskSet[v.Typ] = struct{}{}

		isDailyReset = false
		if _, ok := svrTaskTypSet[v.Typ]; ok {
			isDailyReset = true
		}
		tqtDailyResetTaskList = append(tqtDailyResetTaskList, TqtDailyResetTask{
			Typ:          v.Typ,
			TypName:      taskMap[v.Typ],
			IsDailyReset: isDailyReset,
		})
	}

	// 任务奖励配置
	tqtActivityTaskList := make([]TqtActivityTask, 0, len(svrActivityTask.Item))
	for _, v := range svrActivityTask.Item {
		tqtActivityTaskList = append(tqtActivityTaskList, TqtActivityTask{
			No:         v.No,
			Typ:        v.Typ,
			TypName:    taskMap[v.Typ],
			RequireVal: v.RequireVal,
			Award:      SvrToTqtAwards(ctx, v.Award),
		})
	}

	activityTaskAgg = TqtActivityTaskAgg{
		ActivityTaskList:   tqtActivityTaskList,
		ShowTyp:            TaskShowTyp(svrActivityTask.Item[0].ShowTyp),
		DailyResetTaskList: tqtDailyResetTaskList,
	}

	return
}

func ToSvrActivityTaskOne(activityTaskAgg TqtActivityTaskAgg) (svrActivityTask SvrActivityTask) {
	// 任务类型重置 => 仅存放需要重置的任务类型
	svrDailyResetTask := make([]int, 0, len(activityTaskAgg.DailyResetTaskList))
	for _, item := range activityTaskAgg.DailyResetTaskList {
		if item.IsDailyReset == true {
			svrDailyResetTask = append(svrDailyResetTask, item.Typ)
		}
	}

	// 任务奖励配置
	svrActivityTaskItem := make([]SvrActivityTaskItem, len(activityTaskAgg.ActivityTaskList))
	for i, v := range activityTaskAgg.ActivityTaskList {
		svrActivityTaskItem[i] = SvrActivityTaskItem{
			No:         v.No,
			Typ:        v.Typ,
			RequireVal: v.RequireVal,
			Award:      TqtToSvrAwards(v.Award),
			ShowTyp:    activityTaskAgg.ShowTyp.Val(),
		}
	}
	svrActivityTask = SvrActivityTask{
		Item:           svrActivityTaskItem,
		DailyResetTask: svrDailyResetTask,
	}

	return
}
